﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace WindowsStyle
{
    public static class ListboxHelper
    {
        private static readonly Dictionary<ListBox, HashSet<object>> _pendingUpdates = new();

        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached(
            "SelectedItems",
            typeof(IList),
            typeof(ListboxHelper),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChanged));

        private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not ListBox listBox) return;

            // 清理旧事件监听
            if (e.OldValue is INotifyCollectionChanged oldCollection)
            {
                oldCollection.CollectionChanged -= (s, args) => UpdateListBoxSelection(listBox);
            }

            // 初始化同步
            UpdateListBoxSelection(listBox);

            // 监听 ViewModel 集合变化
            if (e.NewValue is INotifyCollectionChanged newCollection)
            {
                newCollection.CollectionChanged += (s, args) => UpdateListBoxSelection(listBox);
            }

            // 处理 ListBox 选择变化
            listBox.SelectionChanged += (s, args) =>
            {
                if (_pendingUpdates.TryGetValue(listBox, out var cache) && cache.Count > 0) return;

                UpdateViewModelSelection(listBox);
            };
        }

        private static void UpdateViewModelSelection(ListBox listBox)
        {
            var selectedItems = GetSelectedItems(listBox);
            if (selectedItems == null) return;

            // 使用临时集合防止重入
            var newSelection = listBox.SelectedItems.Cast<object>().ToArray();

            // 批量更新（先比较差异）
            if (selectedItems.Count == newSelection.Length &&
                selectedItems.Cast<object>().SequenceEqual(newSelection))
            {
                return;
            }

            // 使用延迟更新防止重入
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                selectedItems.Clear();
                foreach (var item in newSelection)
                {
                    selectedItems.Add(item);
                }
            }), DispatcherPriority.DataBind);
        }

        private static void UpdateListBoxSelection(ListBox listBox)
        {
            if (!_pendingUpdates.TryGetValue(listBox, out var cache))
            {
                cache = new HashSet<object>();
                _pendingUpdates[listBox] = cache;
            }

            try
            {
                var selectedItems = GetSelectedItems(listBox);
                if (selectedItems == null) return;

                // 缓存当前操作
                cache.UnionWith(selectedItems.Cast<object>());

                // 批量更新 ListBox
                listBox.SelectedItems.Clear();
                foreach (var item in selectedItems)
                {
                    listBox.SelectedItems.Add(item);
                }
            }
            finally
            {
                cache.Clear();
            }
        }

        public static void SetSelectedItems(DependencyObject element, IList value) =>
            element.SetValue(SelectedItemsProperty, value);

        public static IList GetSelectedItems(DependencyObject element) =>
            (IList)element.GetValue(SelectedItemsProperty);
    }

}
